home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / NOISE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  6.7 KB  |  264 lines

  1. /* noise.c - by Simon Hui, 3Dfx Interactive */
  2.  
  3. /* create an octave by filtering randomly generated noise */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <math.h>
  8. #include <GL/glut.h>
  9.  
  10. #if !defined(GL_VERSION_1_1) && !defined(GL_VERSION_1_2)
  11. #define glBindTexture glBindTextureEXT
  12. #endif
  13.  
  14.  
  15. static GLint texxsize = 256, texysize = 256;
  16. static GLint winxsize = 512, winysize = 512;
  17. static GLint freq = 4;
  18.  
  19. /* texture object names */
  20. static GLuint basistex = 1;
  21. static GLuint noisetex = 2;
  22.  
  23. void
  24. init_texture(void) {
  25.   int i, j, n;
  26.   int w, h;
  27.   GLubyte *basis, *tex;
  28.   
  29.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  30.   basis = (GLubyte *) malloc(texxsize * texysize);
  31.   w = texxsize / 2;
  32.   h = texysize / 2;
  33.   for (j=0; j < h; j++) {
  34.     for (i=0; i < w; i++) {
  35.       GLint r;
  36.       float u = i / (w - 1.0);
  37.       float v = j / (h - 1.0);
  38.       float f = 3 * u * u - 2 * u * u * u;
  39.       float g = 3 * v * v - 2 * v * v * v;
  40.       
  41.       /* basis is a bicubic spline */
  42.       r = f * g * 0xff;
  43.  
  44.       /* reflect around x and y axes */
  45.       basis[j * texxsize + i] = r;
  46.       basis[j * texxsize + texxsize-i-1] = r;
  47.       basis[(texysize-j-1) * texxsize + i] = r;
  48.       basis[(texysize-j-1) * texxsize + texxsize-i-1] = r;
  49.     }
  50.   }
  51.   glBindTexture(GL_TEXTURE_2D, basistex);
  52.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  53.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  54.   glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texxsize, texysize, 0,
  55.            GL_RED, GL_UNSIGNED_BYTE, basis);
  56.   free(basis);
  57.  
  58.   tex = (GLubyte *) malloc(4 * texxsize * texysize);
  59.   for (n=0; n < 4; n++) {
  60.     for (j=0; j < texysize; j++) {
  61.       for (i=0; i < texxsize; i++) {
  62.     int r = rand();
  63.     
  64.     /* mix it up a little more */
  65.     r = ((r & 0xff) + ((r & 0xff00) >> 8)) & 0xff;
  66.  
  67.     tex[j*texxsize + i] = r;
  68.       }
  69.     }
  70.     glBindTexture(GL_TEXTURE_2D, noisetex + n);
  71.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  72.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  73.     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texxsize, texysize, 0,
  74.          GL_RED, GL_UNSIGNED_BYTE, tex);
  75.   }
  76.   free(tex);
  77. }
  78.  
  79. void
  80. init(void) {
  81.   glClearColor(0.0, 0.0, 0.0, 1.0);
  82.   glMatrixMode(GL_PROJECTION);
  83.   glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
  84.   glMatrixMode(GL_MODELVIEW);
  85.   glViewport(0, 0, winxsize, winysize);
  86.   glBlendFunc(GL_DST_COLOR, GL_ZERO);
  87.  
  88.   glEnable(GL_TEXTURE_2D);
  89.   init_texture();
  90. }
  91.  
  92. void
  93. draw_basis(int tsize, int ssize, int xadj, int yadj) {
  94.   float tilessize = 1.0 / ssize;
  95.   float tiletsize = 1.0 / tsize;
  96.   float xoff = (xadj - 0.5) * 0.5 * tilessize;
  97.   float yoff = (yadj - 0.5) * 0.5 * tiletsize;
  98.   float xo, yo;
  99.   int i, j;
  100.  
  101.   glBindTexture(GL_TEXTURE_2D, basistex);
  102.   glMatrixMode(GL_TEXTURE);
  103.   glLoadIdentity();
  104.  
  105.   /* draw as many copies of the basis function as needed for this frequency */
  106.   for (j=0; j < tsize; j++) {
  107.     for (i=0; i < ssize; i++) {
  108.       xo = xoff + i * tilessize;
  109.       yo = yoff + j * tiletsize;
  110.       glBegin(GL_TRIANGLE_STRIP);
  111.       glTexCoord2f(0.f, 0.f); glVertex2f(xo, yo); 
  112.       glTexCoord2f(0.f, 1.f); glVertex2f(xo, yo + tiletsize); 
  113.       glTexCoord2f(1.f, 0.f); glVertex2f(xo + tilessize, yo); 
  114.       glTexCoord2f(1.f, 1.f); glVertex2f(xo + tilessize, yo + tiletsize); 
  115.       glEnd();
  116.     }
  117.   }
  118.   glFinish();
  119. }
  120.  
  121. void
  122. draw_noise_texture(int tsize, int ssize, int xadj, int yadj, int texname) {
  123.   float tilessize = 1.0 / ssize;
  124.   float tiletsize = 1.0 / tsize;
  125.   float xoff = (xadj - 0.5) * 0.5 * tilessize;
  126.   float yoff = (yadj - 0.5) * 0.5 * tiletsize;
  127.   float scale = 1.0 / (texxsize / ssize);
  128.  
  129.   glBindTexture(GL_TEXTURE_2D, texname);
  130.  
  131.   /* scale the texture matrix to get a noise pattern of desired frequency */
  132.   glMatrixMode(GL_TEXTURE);
  133.   glLoadIdentity();
  134.   glScalef(scale,scale,scale);
  135.  
  136.   glBegin(GL_TRIANGLE_STRIP);
  137.   glTexCoord2f(0.f, 0.f); glVertex2f(xoff, yoff); 
  138.   glTexCoord2f(0.f, 1.f); glVertex2f(xoff, yoff+1.0); 
  139.   glTexCoord2f(1.f, 0.f); glVertex2f(xoff + 1.0, yoff); 
  140.   glTexCoord2f(1.f, 1.f); glVertex2f(xoff + 1.0, yoff + 1.0); 
  141.   glEnd();
  142.   glFlush();
  143. }
  144.  
  145. /* menu choices */
  146. enum {
  147.   BASIS, NOISE, BASIS_TIMES_NOISE, OCTAVE, HIGHER_FREQ, LOWER_FREQ, QUIT=27
  148. };
  149.  
  150. GLint showmode = BASIS_TIMES_NOISE;
  151.  
  152. void
  153. display(void) {
  154.   switch (showmode) {
  155.  
  156.   case BASIS:
  157.     glClear(GL_COLOR_BUFFER_BIT);
  158.     draw_basis(freq, freq, 0, 0);
  159.     break;
  160.  
  161.   case NOISE:
  162.     glClear(GL_COLOR_BUFFER_BIT);
  163.     draw_noise_texture(freq, freq, 0, 0, noisetex);
  164.     break;
  165.  
  166.   case BASIS_TIMES_NOISE:
  167.     glClear(GL_COLOR_BUFFER_BIT);
  168.     glDisable(GL_BLEND);
  169.     draw_basis(freq, freq, 0, 0);
  170.     glEnable(GL_BLEND);
  171.     draw_noise_texture(freq, freq, 0, 0, noisetex);
  172.     glDisable(GL_BLEND);
  173.     break;
  174.  
  175.   case OCTAVE:
  176.  
  177.     /* put four sets together to get the final octave */
  178.  
  179.     glClear(GL_COLOR_BUFFER_BIT);
  180.     glDisable(GL_BLEND);
  181.     draw_basis(freq, freq, 0, 0);
  182.     glEnable(GL_BLEND);
  183.     draw_noise_texture(freq, freq, 0, 0, noisetex);
  184.     glAccum(GL_LOAD, 1.0);
  185.  
  186.     glClear(GL_COLOR_BUFFER_BIT);
  187.     glDisable(GL_BLEND);
  188.     draw_basis(freq, freq, 1, 0);
  189.     glEnable(GL_BLEND);
  190.     draw_noise_texture(freq, freq, 1, 0, noisetex + 1);
  191.     glAccum(GL_ACCUM, 1.0);
  192.  
  193.     glClear(GL_COLOR_BUFFER_BIT);
  194.     glDisable(GL_BLEND);
  195.     draw_basis(freq, freq, 0, 1);
  196.     glEnable(GL_BLEND);
  197.     draw_noise_texture(freq, freq, 0, 1, noisetex + 2);
  198.     glAccum(GL_ACCUM, 1.0);
  199.  
  200.     glClear(GL_COLOR_BUFFER_BIT);
  201.     glDisable(GL_BLEND);
  202.     draw_basis(freq, freq, 1, 1);
  203.     glEnable(GL_BLEND);
  204.     draw_noise_texture(freq, freq, 1, 1, noisetex + 3);
  205.     glAccum(GL_ACCUM, 1.0);
  206.  
  207.     glDisable(GL_BLEND);
  208.     glClear(GL_COLOR_BUFFER_BIT);
  209.     glAccum(GL_RETURN, 1.0);
  210.     break;
  211.   }
  212.   glFlush();
  213. }
  214.  
  215. void
  216. reshape(int w, int h) {
  217.   glViewport(0, 0, w, h);
  218.   glutPostRedisplay();
  219. }
  220.  
  221. void
  222. menu(int value) {
  223.   switch (value) {
  224.   case BASIS:
  225.   case NOISE:
  226.   case BASIS_TIMES_NOISE:
  227.   case OCTAVE:
  228.     showmode = value;
  229.     break;
  230.   case HIGHER_FREQ:
  231.     if (freq < texxsize) freq *= 2;
  232.     break;
  233.   case LOWER_FREQ:
  234.     freq /= 2;
  235.     if (freq < 2) freq = 2;
  236.     break;
  237.   case QUIT:
  238.     exit(0);
  239.   }
  240.   glutPostRedisplay();
  241. }
  242.  
  243. int
  244. main(int argc, char** argv) {
  245.   glutInitWindowSize(winxsize, winysize);
  246.   glutInit(&argc, argv);
  247.   glutInitDisplayMode(GLUT_RGBA | GLUT_ACCUM);
  248.   (void)glutCreateWindow("filtered noise function");
  249.   init();
  250.   glutDisplayFunc(display);
  251.   glutReshapeFunc(reshape);
  252.   glutCreateMenu(menu);
  253.   glutAddMenuEntry("Show One Basis", BASIS);
  254.   glutAddMenuEntry("Show One Noise", NOISE);
  255.   glutAddMenuEntry("Show One Basis x Noise", BASIS_TIMES_NOISE);
  256.   glutAddMenuEntry("Show Octave", OCTAVE);
  257.   glutAddMenuEntry("Higher Frequency", HIGHER_FREQ);
  258.   glutAddMenuEntry("Lower Frequency", LOWER_FREQ);
  259.   glutAddMenuEntry("Quit", QUIT);
  260.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  261.   glutMainLoop();
  262.   return 0;             /* ANSI C requires main to return int. */
  263. }
  264.